﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI.WebControls;
using System.Web.UI;
using System.Web;
using System.Globalization;

namespace MyClub.Web.UI.WebControls
{
    /// <summary>
    /// Binds the value of a <see cref="System.Web.Routing.RouteData"/> value to a parameter object.
    /// </summary>
    public sealed class RouteDataParameter: Parameter
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="RouteDataParameter"/> class.
        /// </summary>
        public RouteDataParameter()
        {
        }

        /// <summary>
        /// Gets or sets the value key.
        /// </summary>
        /// <value>The value key.</value>
        public string ValueKey 
        {
            get { return (string)ViewState["ValueKey"]; }
            set { ViewState["ValueKey"] = value; }
        }

        /// <summary>
        /// Gets or sets a value indicating whether to throw an exception if <see cref="ValueKey"/> is missing.
        /// </summary>
        /// <value><c>true</c> if [throw if key missing]; otherwise, <c>false</c>.</value>
        public bool ThrowIfKeyMissing { get; set; }

        /// <summary>
        /// Updates and returns the value of the <see cref="T:System.Web.UI.WebControls.Parameter"/> object.
        /// </summary>
        /// <param name="context">The current <see cref="T:System.Web.HttpContext"/> of the request.</param>
        /// <param name="control">The <see cref="T:System.Web.UI.Control"/> the parameter is bound to. If the parameter is not bound to a control, the <paramref name="control"/> parameter is ignored.</param>
        /// <returns>
        /// An object that represents the updated and current value of the parameter.
        /// </returns>
        protected override object Evaluate(System.Web.HttpContext context, System.Web.UI.Control control)
        {
            if (context == null)
                throw new ArgumentNullException("context");
            
            // Verify that the value key has been specified.
            if (string.IsNullOrEmpty(ValueKey))
                throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, Properties.Resources.RouteDataParameter_ValueKeyCannotBeNullOrEmpty, Name));

            // Check that the page is routed.
            var page = context.CurrentHandler as Page;
            if (!page.IsRouted())
                throw new InvalidOperationException(Properties.Resources.RouteDataParameter_PageMustBeRouted);

            var requestContext = page.GetRequestContext();

            // Check if the value key exists.
            if (!requestContext.RouteData.Values.ContainsKey(ValueKey))
            {
                if (ThrowIfKeyMissing)
                    throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, Properties.Resources.RouteDataParameter_RouteDataValueMissing, ValueKey));
                else
                    return null;
            }

            // Evaluate value
            object value = requestContext.RouteData.Values[ValueKey];

            if (value == null)
                return value;

            if (Convert.GetTypeCode(value) == Type)
                return value;

            return Convert.ChangeType(value, Type, CultureInfo.CurrentUICulture);
        }
    }
}
